#ifndef ANALYSISPRO_H
#define ANALYSISPRO_H

/* Protocol */
#include <QDebug>
#include <QString>
#include <QVector>
#include <QMap>
#include <QtXml>
#include <QtEndian>
#include <QDataStream>
#include <QFileDialog>
#include <QDomDocument>

/* UDPSocket */
#include <QHash>
#include <QSet>
#include <QByteArray>
#include <QUdpSocket>
#include <QHostAddress>
#include <QFunctionPointer>

/* OracleDB */
#include <QVector>
#include <QSettings>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>

/* RTI-DDS */
#include "../dds/ddsmodular.h"

#include "frameinterface.h"

#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#endif

#ifdef __WINDOWS_
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#endif

#ifdef __unix
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

#ifdef linux
#include<netinet/in.h>
#include <arpa/inet.h>
#endif

#define cout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]"

typedef void(*myfunction)(QByteArray&);

/*
 * @file protocol.h
 * @brief XXXXXXXXXX
 * @date xxxx-xx-xx
 */


/**********************************/
           /* 解析协议 */
/**********************************/

typedef struct ProtocolFiled     // 协议字段
{
    QString filedName;           // 名称
    QString 类型为;           // 类型为
    QString filedMethod;         // 方法
    QString filedMeasurement;    // 单位
    QString filedInstruction;    // 说明
}PF;


typedef struct ProtocolProperty  // 协议属性
{
    QString key;
    QString value;
}PP;

typedef struct ProtocolData  // 解析后结果
{
    QString rowNum;             // 行序号
    QString rowProperty;        // 行属性
    QString rowValue;           // 行值
    QString rowDisplay;         // 行显示
    QString rowInstruction;     // 行说明
}PD;

using VecPF = QVector<PF>;
using VecPP = QVector<PP>;
using VecPD = QVector<PD>;

typedef struct Protocol {       // 协议集合
    VecPF vpf;
    VecPP vpp;
}PR;


class MeteoMothod
{
public:
    ~MeteoMothod();
    static QString baseMothod(const QByteArray&, const long, const QString&, const QString&);   // 解析方法函数
    static QString toBinString(const long&, const QString&);       // 转换为二进制字符串
    static int complement2Dec(const QByteArray&);                  // 十六进制补码转换为整数
    QString uint2run(const QString&, const QByteArray&);           // 类型为 uint 方法
    QString int2run(const QString&, const QByteArray&);            // 类型为 int 方法
    QString ushort2run(const QString&, const QByteArray&);         // 类型为 ushort 方法
    QString short2run(const QString&, const QByteArray&);          // 类型为 short 方法
    QString byte2run(const QString&, const QByteArray&);           // 类型为 byte 方法
    QString string2run(const QByteArray&);                         // 类型为 string 解析方法

private:
    static bool m_ok;           // 填参占用，无实质意义
};

class ParseProtocol             // 解析协议类
{
public:
    ParseProtocol() = delete;
    // 构造函数，参数为xml文件地址，必需
    ParseProtocol(const QString&);
    ~ParseProtocol();
    /*
     * @brief 解析报文
     * param[in] const   data(数据)、dataLen(数据长度)
     */
    VecPD ParsePacketData(const QByteArray&, const int);  // 解析数据
    void AnalyticProcess(const QByteArray&, const int);   // 协议分析
    static void ReadXmlProtocol();         // 读取已存在协议

private:
    static QFile m_file;                   // 协议 xml文件
    static PR m_protocol;                  // 解析后数据集合
    static QMap<QString, PR> m_mprotocol;  // 报文

private:
    PD m_prodata;              // 解析后数据
    VecPD m_vprodata;          // 结果集
    int m_pos;                 // 解析位置指针
    bool m_ok;                 // 填参，无实质意义
    QString m_mesflag;         // 报文标示
    MeteoMothod* m_mothod;     // 解析方法
};


/**********************************/
           /* 数据转换 */
/**********************************/

typedef struct ValueTypeMothod {
    QString value;
    QString type;
    QString mothod;
}VTM;

using VecVTM = QVector<VTM>;

class ConverMothod
{
public:
    ConverMothod();
    ~ConverMothod();
    QByteArray uint2run(const QString&, const QString&);           // 类型为 uint 方法
    QByteArray int2run(const QString&, const QString&);            // 类型为 int 方法
    QByteArray ushort2run(const QString&, const QString&);         // 类型为 ushort 方法
    QByteArray short2run(const QString&, const QString&);          // 类型为 short 方法
    QByteArray byte2run(const QString&, const QString&);           // 类型为 byte 方法
    QByteArray string2run(const QString&, const int&);             // 类型为 string 解析方法
private:
    QByteArray m_data;          // 暂存数据
    bool m_ok;                  // 填参占用，无实质意义
};

class ConvertData {
public:
    ConvertData() = delete;
    /*
     * @brief 构造函数
     * @param[in] filename-xml文件地址, data-原始数据：at(0)-协议名称
     */
    ConvertData(const QString&, const QStringList&);
    ~ConvertData();
    static void ReadXmlProtocol(const QString&);   // 读取已存在协议
    void ConvertRowData();         // 存储原始数据函数
    QByteArray ConvertNewData();   // 转换为非原始数据
    int getProSize();

private:
    static QFile m_file;
    static QMap<QString, PR> m_protocol;  // 报文

private:
    QStringList m_rowdata;         // 原始数据
    QByteArray m_data;             // 转换后的数据
    QString m_proname;             // 协议名称
    VecVTM m_vtm;                  // 数据字段检索
    int m_prosize;                 // 获取数据长度
    int m_pos;                     // 原始数据位置指针
    ConverMothod* m_mothod;
};


/**********************************/
        /* OracleDB操作类 */
/**********************************/

/*
 * @file oracledb.h
 * @brief oracle数据库操作类
 * @date 2020-8-24
 */

using VVQ = QVector<QVector<QVariant>>;

class OracleDB {
public:
    OracleDB() = delete;
    /*
     * @brief oracleDB类 构造函数
     * param[in] filename：配置文件  ip：IP地址  port：端口  username：用户名  password：密码
     */
    OracleDB(const QString& filename);
    ~OracleDB();

    // 初始化，连接oracle数据库
    static void connectOracleDB(const QString&, const QString&, const QString&, const QString&);
    VVQ sqlQuery(const QString&); // sql操作，查询
    bool sqlOpt(const QString&);  // sql操作，增、删、改
    QSqlQuery getSqlQuery();

private:
    static QSqlDatabase m_db;     // 数据库句柄
    static bool m_blsConn;        // 是否成功连接
    QSqlQuery m_query;            // 数据库执行句柄
    bool m_ok;                    // sql语句是否成功执行
    VVQ m_res;                    // sql查询语句 结果集
};


/**********************************/
           /* 接口管理类 */
/**********************************/

class InterfaceManager : public IFrame {

/* Protocol Manager */
public:
    InterfaceManager();
    InterfaceManager(const QString&);                             // 配置文件（Oracle数据库）
    ~InterfaceManager();
    QByteArray protocol2Data(QString, QStringList) override;      // 协议内容到数据的转换
    VecPD data2Protocol(QString, QByteArray) override;            // 数据到协议内容的解析

private:
    ParseProtocol* m_protocol;
    ConvertData* m_conver;

/* UDP Manager */
public:
    void sendMsg(QString, QString, QByteArray) override;          // 发送UDP消息
    void sendMulticastMsg(QString, QByteArray) override;          // 发送UDP组播消息
    /*
     * @brief 创建一个UDP接受者
     * @param[in] QString 端口
     * @param[in] func 回调函数，需要执行的功能函数
     */
    void createReceiver(QString, void(*func)(QByteArray&)) override;
private:
    static QHash<QString, QVector<myfunction>> m_funcset;
    QUdpSocket* m_receiver;
    QHostAddress m_castaddr{"224.0.0.2"};

/* OracleDB Manager */
public:
    QVector<QVector<QVariant>> sqlQuery(const QString&) override; // 数据库查询操作
    bool sqlOpt(const QString&) override;                         // 数据库增删改以及其他操作
    QSqlQuery getSqlQuery() override;                             // 获取元素SqlQuery值

private:
    OracleDB* m_oracledb;

/* RTI-DDS Manager */
/* RTTI-DDS 封装 功能解释、文档说明详见ddsmodular.h文件及 .cpp文件 */
public:
    // Publisher
    void createTopic(const std::string&,
                     bool, bool redundancy = false,
                     const int& priority = 0) override;           // 创建话题

    void publish4Top(const std::string&, const TupMsg&) override; // 发布话题
    void deleteTopic(const std::string&) override;                // 删除话题

    // Subscriber
    /*
     * @brief 订阅话题
     * @param[in] 话题名
     * @param[in] 回调函数，需要执行的功能
     * @param[in] 是否冗余
     */
    void listenTopic(const std::string&, Func fun, bool, bool redundancy = false) override;
    void cancelTopic(const std::string&) override;                // 取消订阅

private:
    Publisher* m_pub;
    Subscriber* m_sub;
};

#endif // ANALYSISPRO_H
